import { Category, ICategory } from '../models/category'
import {
  DatabaseError,
  NotFoundError,
  ValidationError
} from '../errors/CustomError'
import { isMongoError } from '../errors/MongoError'
import { listToTree } from '../utils/utils'

class CategoryService {
  // 创建分类
  async create(categoryData: Partial<ICategory>): Promise<ICategory> {
    try {
      // 设置默认层级为1（顶级分类）
      if (!categoryData.level) {
        categoryData.level = 1
      }

      const category = new Category(categoryData)
      return await category.save()
    } catch (error) {
      if (isMongoError(error) && error.code === 11000) {
        const mongoError = error as any
        if (mongoError.keyValue?.name) {
          throw new ValidationError('分类名称已存在')
        }
        if (mongoError.keyValue?.code) {
          throw new ValidationError('分类编码已存在')
        }
        throw new ValidationError('分类数据重复')
      }

      if (error instanceof Error && error.name === 'ValidationError') {
        throw new ValidationError('分类数据验证失败', (error as any).errors)
      }

      throw new DatabaseError('创建分类失败')
    }
  }

  // 删除分类
  async delete(id: number): Promise<boolean> {
    try {
      const result = await Category.findOneAndDelete({ id })

      if (!result) {
        throw new NotFoundError('分类未找到')
      }

      return true
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('删除分类失败')
    }
  }

  // 删除分类及其子分类
  async deleteWithChildren(id: number): Promise<boolean> {
    try {
      // 查找要删除的分类
      const category = await Category.findOne({ id })

      if (!category) {
        throw new NotFoundError('分类未找到')
      }

      // 递归查找所有子分类ID
      const allIdsToDelete = await this.getAllChildCategoryIds(id)
      allIdsToDelete.push(id) // 添加当前分类ID

      // 批量删除所有相关分类
      await Category.deleteMany({ id: { $in: allIdsToDelete } })

      return true
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('删除分类失败')
    }
  }

  // 更新分类
  async update(
    id: number,
    updateData: Partial<ICategory>
  ): Promise<ICategory | null> {
    try {
      // 移除不能更新的字段
      const { id: categoryId, created_at, ...updateFields } = updateData

      const category = await Category.findOneAndUpdate({ id }, updateFields, {
        new: true
      })

      if (!category) {
        throw new NotFoundError('分类未找到')
      }

      return category
    } catch (error) {
      if (isMongoError(error) && error.code === 11000) {
        const mongoError = error as any
        if (mongoError.keyValue?.name) {
          throw new ValidationError('分类名称已存在')
        }
        if (mongoError.keyValue?.code) {
          throw new ValidationError('分类编码已存在')
        }
        throw new ValidationError('分类数据重复')
      }

      if (error instanceof Error && error.name === 'ValidationError') {
        throw new ValidationError('分类数据验证失败', (error as any).errors)
      }
      throw new DatabaseError('更新分类失败')
    }
  }

  // 查询所有分类
  async findAll(type?: string): Promise<ICategory[] | any[]> {
    try {
      const categories = await Category.find({})
      const data = categories.map((category) => category.toJSON())

      if (type === 'tree') {
        return listToTree(data, 'parent_id', 'id')
      }
      return data
    } catch (error) {
      throw new DatabaseError('查询分类列表失败')
    }
  }

  // 查询单个分类
  async findOne(id: number): Promise<ICategory | null> {
    try {
      const category = await Category.findOne({ id })

      if (!category) {
        throw new NotFoundError('分类未找到')
      }

      return category
    } catch (error) {
      if (error instanceof NotFoundError) {
        throw error
      }
      throw new DatabaseError('查询分类失败')
    }
  }

  // 根据分类id查询所有子分类
  async findByParentId(parentId: number | null): Promise<ICategory[]> {
    try {
      // 先获取父分类及所有子分类
      let categories: ICategory[] = []

      if (parentId !== null) {
        // 获取指定的父分类
        const parentCategory = await Category.findOne({ id: parentId })
        if (parentCategory) {
          categories.push(parentCategory.toObject())
        }

        // 获取所有子分类
        const allChildIds = await this.getAllChildCategoryIds(parentId)
        const childCategories = await Category.find({
          id: { $in: allChildIds }
        })
        categories = categories.concat(
          childCategories.map((category) => category.toObject())
        )
      } else {
        // 如果parentId为null，获取所有分类
        const allCategories = await Category.find({})
        categories = allCategories.map((category) => category.toObject())
      }

      // 转换为树形结构
      return listToTree(categories, 'parent_id', 'id')
    } catch (error) {
      throw new DatabaseError('查询分类树形结构失败')
    }
  }

  // 添加一个辅助方法用于获取所有子分类ID
  private async getAllChildCategoryIds(parentId: number): Promise<number[]> {
    try {
      // 查找直接子分类
      const directChildren = await Category.find({ parent_id: parentId })
      let allChildIds: number[] = directChildren.map((child) => child.id)

      // 递归查找子分类的子分类
      for (const child of directChildren) {
        const grandChildIds = await this.getAllChildCategoryIds(child.id)
        allChildIds = allChildIds.concat(grandChildIds)
      }

      return allChildIds
    } catch (error) {
      throw new DatabaseError('查询子分类失败')
    }
  }
}

export default new CategoryService()
